#ifndef _SESSION_DATA_H
#define _SESSION_DATA_H

#include <stdint.h>

#include "crypto.h"

/**
 * Transport encryption and integrity keys
 *
 * @TEK - Transport Encryption Key.
 * @TIK - Transport Integrity Key.
 */
typedef struct __attribute__((__packed__)) tek_tik_t {
    aes_128_key tek;
    aes_128_key tik;
} tek_tik;

/*
 * find detail from
 * https://openanolis.cn/sig/Hygon-Arch/doc/1272157030987431940?lang=zh
 */

/**
 * LAUNCH_START Session Data Buffer
 *
 * @nonce       - An arbitrary 128 bit number.
 * @wrap_tk     - The CSV transport encryption and integrity keys.
 * @wrap_iv     - 128 bit initializer vector.
 * @wrap_mac    - Wrap_tektik hash message authentication code.
 * @session_mac - Session hash message authentication code.
 * @reserved1   - Obsolete
 * @reserved2   - Obsolete
 * @ms_enc      - User's master key, encrypted by PDH public key
 * @vm_digest   - Digest of VM bios
 * @reserved3   - Obsolete
 * @vm_id       - VM ID
 * @vm_version  - VM Version
 * @user_data   - A user self-defined string
 * @sig         - Session data signature signed by user's private key
 *
 */
typedef struct __attribute__((__packed__)) session_buf_t {
    nonce_128    nonce;
    tek_tik      wrap_tk;
    iv_128       wrap_iv;
    hmac_sha_256 wrap_mac;
    hmac_sha_256 session_mac;
    /* for backward compatibility */
    uint8_t      reserved1[16];
    uint8_t      reserved2[148];
    uint8_t      ms_enc[MS_ENC_SIZE * 2];
    uint8_t      vm_digest[HASH_BLOCK_LEN];
    uint8_t      reserved3[32];
    uint8_t      vm_id[VM_ID_SIZE];
    uint8_t      vm_version[VM_VERSION_SIZE];
    uint8_t      user_data[USER_DATA_SIZE];
    uint8_t      sig[SESSION_SIG_SIZE];
} session_buf;


/**
 * csv guest policy, 4 bytes
 *
 * @nodebug     - disallow debug to guest
 * @noks        - disallow sharing keys with other guests
 * @csv2        - guest is csv2
 * @nosend      - disallow sending the guest to another platform
 * @domain      - disallow sending the guest to another platform of another domain
 * @csv         - guest is csv.
 * @csv3        - guest is csv3
 * @asid_reuse  - multiple guest can reuse the same asid
 * @hsk_version - HSK version
 * @cek_version - CEK version
  */

typedef struct guest_policy_t {
    uint16_t nodebug     : 1,
             noks        : 1,
             csv2        : 1,
             nosend      : 1,
             domain      : 1,
             csv         : 1,
             csv3        : 1,
             asid_reuse  : 1,
             hsk_version : 4,
             cek_version : 4;
    uint8_t  api_major;
    uint8_t  api_minor;
} guest_policy;


/**
 * extra data for CSV3 measurement
 *
 * @command_id     - command id to the firmware (CSV3_LAUNCH_ENCRYPT_DATA / CSV3_LAUNCH_ENCRYPT_VMCB)
 * @gpa            - guest physical address
 * @vcpu_id        - vcpu's id
 * @data_size      - data size of next section to be measured
  */

typedef struct __attribute__((packed)) csv3_measure_update_extra_data {
    uint32_t command_id;
    union {
        uint64_t gpa;
        uint64_t vcpu_id;
    };
    uint64_t data_size;
} csv3_measure_update_extra_data_t;

typedef enum {
    CSV3_LAUNCH_ENCRYPT_DATA = 0x01,
    CSV3_LAUNCH_ENCRYPT_VMCB = 0x02,
} csv3_measure_cmd_e;


#define SESSION_MAC_SIZE  ((((session_buf *)0)->sig - ((session_buf *)0)->ms_enc) + sizeof(guest_policy))


#define PDH_FILENAME                      "pdh.cert"
#define GUEST_POLICY_FILENAME             "guest_policy.txt"
#define GUEST_OWNER_DH_FILENAME           "guest_owner_dh_raw.cert"
#define GUEST_OWNER_DH_FILENAME_BASE64    "guest_owner_dh.cert"
#define GUEST_PRIV_KEY_FILENAME           "guest_owner_dh_private_key.bin"
#define GUEST_TEK_TIK_FILENAME            "guest_tek_tik.bin"
#define LAUNCH_BLOB_FILENAME              "launch_blob_raw.bin"
#define LAUNCH_BLOB_FILENAME_BASE64       "launch_blob.bin"
#define GUEST_MASTER_KEY_FILENAME         "guest_master_key.bin"

#endif
